#include "Int_EEPROM.h"

// 定义iic引脚 - 根据原理图确认
#define IIC_SCL_PORT GPIOB
#define IIC_SDA_PORT GPIOB
#define IIC_SCL_PIN GPIO_Pin_8 // I2C1_SCL
#define IIC_SDA_PIN GPIO_Pin_9 // I2C1_SDA

/**
 * @brief 等待指定事件
 *
 * @param I2Cx
 * @param I2C_EVENT
 * @return 1=成功, 0=超时
 */
uint8_t EEPROM_WaitEvent(I2C_TypeDef *I2Cx, uint32_t I2C_EVENT)
{
    uint32_t Timeout;
    Timeout = 50000;                                   // 增加超时时间
    while (I2C_CheckEvent(I2Cx, I2C_EVENT) != SUCCESS) // 循环等待指定事件
    {
        Timeout--;        // 等待时，计数值自减
        if (Timeout == 0) // 自减到0后，等待超时
        {
            // 超时处理：复位I2C
            I2C_SoftwareResetCmd(I2Cx, ENABLE);
            I2C_SoftwareResetCmd(I2Cx, DISABLE);
            I2C_Cmd(I2Cx, ENABLE);
            return 0; // 返回超时错误
        }
    }
    return 1; // 成功
}

void Int_EEPROM_Init(void)
{
    // 开启时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    // 先禁用I2C，确保干净的初始化
    I2C_Cmd(I2C1, DISABLE);

    // GPIO初始化
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;   // 复用功能模式
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; // 开漏输出
    GPIO_InitStructure.GPIO_Pin = IIC_SCL_PIN | IIC_SDA_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // 内部上拉
    GPIO_Init(IIC_SCL_PORT, &GPIO_InitStructure);

    // 配置GPIO复用功能
    GPIO_PinAFConfig(IIC_SCL_PORT, GPIO_PinSource8, GPIO_AF_I2C1); // PB8 -> I2C1_SCL
    GPIO_PinAFConfig(IIC_SDA_PORT, GPIO_PinSource9, GPIO_AF_I2C1); // PB9 -> I2C1_SDA

    // I2C软件复位
    I2C_SoftwareResetCmd(I2C1, ENABLE);
    I2C_SoftwareResetCmd(I2C1, DISABLE);

    // I2C初始化 - 降低速度提高稳定性
    I2C_InitTypeDef I2C_InitStructure;
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_ClockSpeed = 50000; // 降低到50kHz提高稳定性
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;
    I2C_Init(I2C1, &I2C_InitStructure);

    // 使能I2C
    I2C_Cmd(I2C1, ENABLE);

    // 等待I2C稳定
    Delay(10);
}

uint8_t Int_EEPROM_Write(uint16_t Dev_addr, uint16_t Rag_addr, uint8_t data)
{
    // 等待I2C总线空闲
    uint32_t timeout = 10000;
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) && timeout--)
        ;
    if (timeout == 0)
        return 0;

    // 发送起始信号
    I2C_GenerateSTART(I2C1, ENABLE);
    // 等待发送完成
    if (!EEPROM_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
        return 0;

    // 发送从机地址（写方向）
    I2C_Send7bitAddress(I2C1, Dev_addr << 1, I2C_Direction_Transmitter);
    // 等待发送完成
    if (!EEPROM_WaitEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
        return 0;

    // AT24C512需要发送16位地址：先发送高8位
    I2C_SendData(I2C1, (uint8_t)(Rag_addr >> 8));
    // 等待发送完成
    if (!EEPROM_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
        return 0;

    // 发送地址低8位
    I2C_SendData(I2C1, (uint8_t)(Rag_addr & 0xFF));
    // 等待发送完成
    if (!EEPROM_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
        return 0;

    // 发送数据
    I2C_SendData(I2C1, data);
    // 等待发送完成
    if (!EEPROM_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
        return 0;

    // 发送停止信号
    I2C_GenerateSTOP(I2C1, ENABLE);

    // AT24C512写入周期时间最大10ms，等待写入完成
    Delay(10);

    return 1; // 成功
}

uint8_t Int_EEPROM_Read(uint16_t Dev_addr, uint16_t Rag_addr, uint8_t *data)
{
    // 等待I2C总线空闲
    uint32_t timeout = 10000;
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) && timeout--)
        ;
    if (timeout == 0)
        return 0;

    // 第一阶段：写入寄存器地址
    // 发送起始信号
    I2C_GenerateSTART(I2C1, ENABLE);
    // 等待发送完成
    if (!EEPROM_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
        return 0;

    // 发送从机地址（写方向）
    I2C_Send7bitAddress(I2C1, Dev_addr << 1, I2C_Direction_Transmitter);
    // 等待发送完成
    if (!EEPROM_WaitEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
        return 0;

    // AT24C512需要发送16位地址：先发送高8位
    I2C_SendData(I2C1, (uint8_t)(Rag_addr >> 8));
    // 等待发送完成
    if (!EEPROM_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
        return 0;

    // 发送地址低8位
    I2C_SendData(I2C1, (uint8_t)(Rag_addr & 0xFF));
    // 等待发送完成
    if (!EEPROM_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
        return 0;

    // 第二阶段：读取数据
    // 重新发送起始信号（重复起始）
    I2C_GenerateSTART(I2C1, ENABLE);
    // 等待发送完成
    if (!EEPROM_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
        return 0;

    // 发送从机地址（读方向）
    I2C_Send7bitAddress(I2C1, (Dev_addr << 1) | 0x01, I2C_Direction_Receiver);
    // 等待接收模式选择完成
    if (!EEPROM_WaitEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
        return 0;

    // 在接收最后一个字节之前提前将应答失能
    I2C_AcknowledgeConfig(I2C1, DISABLE);
    // 在接收最后一个字节之前提前申请停止条件
    I2C_GenerateSTOP(I2C1, ENABLE);

    // 等待数据接收完成
    if (!EEPROM_WaitEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED))
        return 0;
    // 接收数据
    *data = I2C_ReceiveData(I2C1);

    // 恢复应答使能
    I2C_AcknowledgeConfig(I2C1, ENABLE);

    return 1; // 成功
}

uint8_t Int_EEPROM_IsDeviceReady(uint16_t Dev_addr)
{
    // 等待I2C总线空闲
    uint32_t timeout = 10000;
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) && timeout--)
        ;
    if (timeout == 0)
        return 0;

    // 发送起始信号
    I2C_GenerateSTART(I2C1, ENABLE);
    // 等待发送完成
    if (!EEPROM_WaitEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
        return 0;

    // 发送从机地址（写方向）
    I2C_Send7bitAddress(I2C1, Dev_addr << 1, I2C_Direction_Transmitter);
    // 等待发送完成
    if (!EEPROM_WaitEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
    {
        // 发送停止信号
        I2C_GenerateSTOP(I2C1, ENABLE);
        return 0;
    }

    // 发送停止信号
    I2C_GenerateSTOP(I2C1, ENABLE);

    return 1; // 设备存在
}
